package com.scvtc.service.security.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.scvtc.domain.dto.common.SystemLoginUser;
import com.scvtc.domain.dto.system.menu.SystemMenuDto;
import com.scvtc.domain.entity.system.SystemMenu;
import com.scvtc.domain.entity.system.SystemRole;
import com.scvtc.domain.entity.system.SystemUser;
import com.scvtc.mapper.system.SystemMenuMapper;
import com.scvtc.mapper.system.SystemRoleMapper;
import com.scvtc.mapper.system.SystemUserMapper;
import com.scvtc.utils.BeanCopyUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.scvtc.constants.SystemConstants.*;
import static com.scvtc.domain.enums.AppHttpCodeEnum.USER_NOT_FIND;

/**
 * @Description: 用户登录实现类
 * @Author: yiFei
 * @date: 2022/4/13 20:22
 */
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private SystemUserMapper systemUserMapper;

    @Resource
    private SystemMenuMapper systemMenuMapper;

    @Resource
    private SystemRoleMapper systemRoleMapper;
    /*
        获取权限信息
     */
    private List<String> permissions;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SystemUser systemUser = systemUserMapper.selectOne(
                new LambdaQueryWrapper<SystemUser>()
                        .eq(SystemUser::getUserName, username)
                        .eq(SystemUser::getStatus, STATUS_ENABLE)
        );
        // 判断用户名是否存在
        // 后台管理系统让用户知道更详细
        if (ObjectUtils.isEmpty(systemUser)) {
            throw new UsernameNotFoundException(USER_NOT_FIND.getMsg());
        }
        List<SystemRole> roles = systemRoleMapper.getRolesByUserId(systemUser.getId());
        Set<Long> role_ids = roles.stream()
                .map(SystemRole::getId)
                .collect(Collectors.toSet());
        // 查询用户菜单
        List<Long> menu_ids = systemMenuMapper.getMenusByRoleIds(role_ids);
        // 封装用户权限 ( 重置 permission )
        permissions = new ArrayList<>();
//        List<String> permission = menus.stream()
//                .distinct()
//                .filter(menu -> MENU_TYPE_BUTTON.equals(menu.getType()))
//                .map(SystemMenu::getPermission)
//                .collect(Collectors.toList());
        // 获取全部菜单来匹配
        List<SystemMenu> allMenus = systemMenuMapper.getAllMenus(0L);
        List<SystemMenuDto> systemMenuDto = recursionMenus(allMenus, menu_ids);
        // 统一返回
        return new SystemLoginUser(systemUser, permissions, systemMenuDto);
    }

    /**
     * 使用递归拿去菜单有用信息
     * <p>
     * int count = 0 再每次 添加元素后 让 nav.get(count) 能拿到值
     * <p>
     * // 如果是 按钮 不需要循环
     * if (MENU_TYPE_BUTTON.equals(menu.getType())){
     * permission.add(menu.getPermission());
     * continue;
     * }
     * <p>
     * // 核心递归循环有子元素的
     * if (menu.getChildren() != null && menu.getChildren().size() > 0 ){
     * nav.get(count).setChildren(recursionMenus(menu.getChildren(),menu_ids));
     * }
     * <p>
     * // 每次增加就进行下一次遍历
     * count++;
     *
     * @param menus
     * @param menu_ids
     * @return
     */
    private List<SystemMenuDto> recursionMenus(List<SystemMenu> menus, List<Long> menu_ids) {
        List<SystemMenuDto> nav = new ArrayList<>();
        int count = 0;
        for (SystemMenu menu : menus) {
            if (menu_ids.contains(menu.getId())) {
                if (MENU_TYPE_BUTTON.equals(menu.getType())) {
                    permissions.add(menu.getPermission());
                    continue;
                } else if (MENU_TYPE_DIRECTORY.equals(menu.getType())) {
                    permissions.add(menu.getPermission());
                }
                nav.add(beanConvert(menu));
                if (menu.getChildren() != null && menu.getChildren().size() > 0) {
                    nav.get(count).setChildren(recursionMenus(menu.getChildren(), menu_ids));
                }
                count++;
            }
        }
        return nav;
    }

    /**
     * Bean 转换
     */
    private SystemMenuDto beanConvert(SystemMenu source) {
        SystemMenuDto systemMenuDto = BeanCopyUtils.copyBean(source, SystemMenuDto.class);
        systemMenuDto.setPermissionName(source.getPermission());
        return systemMenuDto;
    }
}
